<script setup lang="ts">
import RoomStatus from './components/RoomStatus.vue'
import RoomAction from './components/RoomAction.vue'
import RoomMessage from './components/RoomMessage.vue'
// 导入socket.io-client插件
import { io, type Socket } from 'socket.io-client'
import { useUserStore } from '@/stores'
import { useRoute } from 'vue-router'
import { nextTick, onMounted, onUnmounted, provide } from 'vue'
import { ref } from 'vue'
import type { Message, TimeMessages } from '@/types/room.d.ts'
import { MsgType, OrderType } from '@/enums'
import { getConsultOrderDetailService } from '@/api/consult'
import type { ConsultOrderItem, Image } from '@/types/consult'

/**
 * 初始化创建ws长连接（打电话）
 * 1. 通过io函数传入后台ws链接地址和相关参数（token、orderId)
 * 2. 连接建立的相关事件：
 *   - 通过io实例的connect事件，监听连接是否成功
 *   - 通过io实例的error事件，监听连接错误
 *   - 通过io实例的disconnect事件，监听连接断开
 */
let socket: Socket
// 聊天列表
const list = ref<Message[]>([])
const userStore = useUserStore()
const route = useRoute()
const initSocket = () => {
  // 建立连接
  socket = io(import.meta.env.VITE_API_URL, {
    auth: {
      token: `Bearer ${userStore.user?.token}`,
    },
    query: {
      orderId: route.query.orderId,
    },
  })
  // 测试连接成功
  socket.on('connect', () => {
    console.log('浏览器和ws服务器建立连接成功!')
  })
  // 测试连接失败
  socket.on('error', () => {
    console.log('出错了!')
  })
  // 测试连接断开
  socket.on('disconnect', () => {
    console.log('浏览器和ws服务器建立连接断开!')
  })
  // 1. 接收ws服务器给浏览器（患者端）发送的默认消息
  // 说明：{data}: {data添加类型}
  socket.on('chatMsgList', ({ data }: { data: TimeMessages[] }) => {
    const result: Message[] = []
    // 1. 发送消息的时间也放入到result中
    data.forEach((item) => {
      result.push({
        id: item.createTime,
        msgType: MsgType.Notify,
        createTime: item.createTime,
        msg: {
          content: item.createTime,
        },
      })
      // 2. 把items的消息放入到result中
      result.push(...item.items)
    })
    // 3. 把处理好的消息列表result追加到list
    list.value.push(...result)
    console.log(result)
    nextTick(() => {
      // 收到消息后，滚动到最底部
      window.scrollTo(0, document.body.scrollHeight)
    })
  })
  // 2.接收医生回复的消息
  socket.on('receiveChatMsg', async (msg) => {
    console.log('收消息', msg)

    list.value.push(msg)
    // 每次收到消息后，滚动到最底部
    // 说明： list消息列表更新后，直接滚动会失效
    // 原因： vue是异步更新dom
    await nextTick()
    window.scrollTo(0, document.body.scrollHeight)
  })
  // 3. 监听医生订单状态改变，更新订单状态
  socket.on('statusChange', (res: { id: string; status: OrderType }) => {
    getConsultOrderDetail()
    console.log('订单更新了')
  })
}

// 获取问诊订单详情
const orderDetail = ref<ConsultOrderItem>()
const getConsultOrderDetail = async () => {
  const res = await getConsultOrderDetailService(route.query.orderId as string)
  orderDetail.value = res
}

onMounted(() => {
  // 组件挂载时，初始化ws连接
  initSocket()
  getConsultOrderDetail()
})
onUnmounted(() => {
  // 组件销毁时，关闭ws连接
  socket.close()
})

// 发送文字消息
const sendText = (text: string) => {
  // 通过socket.emit('和后台约定的事件名',data)方法发消息给医生（需要ws服务器中转）
  socket.emit('sendChatMsg', {
    from: userStore.user!.id, // 发送消息的人 =》 登录人ID
    to: orderDetail.value?.docInfo?.id, // 接收消息的人 =》 接诊的医生
    msgType: MsgType.MsgText, // 消息类型： 文字消息
    msg: {
      content: text,
    },
  })
}
// 发送图片消息
const sendImage = (img: Image) => {
  socket.emit('sendChatMsg', {
    from: userStore.user?.id!, // 发送消息的人 =》 登录人ID
    to: orderDetail.value?.docInfo?.id, // 接收消息的人 =》 接诊的医生
    msgType: MsgType.MsgImage, // 消息类型： 图片消息
    msg: { picture: img },
  })
}

// 评价成功，修改评价消息状态和数据，切换卡片展示
const completeEva = (score: number) => {
  // 获取评价信息数据
  const item = list.value.find((item) => item.msgType === MsgType.CardEvaForm)
  if (item) {
    item.msg.evaluateDoc = { score }
    item.msgType = MsgType.CardEva
  }
}
// 依赖注入
provide('orderDetail', orderDetail)
provide('completeEva', completeEva)
</script>

<template>
  <div class="room-page">
    <cp-nav-bar title="医生问诊室" />
    <!-- 1. 问诊状态：未接诊、咨询中、问诊结束-->
    <room-status :order-status="orderDetail?.status" :countdown="orderDetail?.countdown" />
    <!-- 2. 问诊聊天列表消息：咨询中的医生和患者的聊天内容（列表） -->
    <room-message :list="list" />
    <!-- 3. 底部操作栏：发消息 -->

    <room-action
      :is-disabled="orderDetail?.status !== OrderType.ConsultChat"
      :order-status="orderDetail?.status"
      @send-text="sendText"
      @send-image="sendImage"
    />
  </div>
</template>
<style lang="scss" scoped>
.room-page {
  padding-top: 90px;
  padding-bottom: 60px;
  min-height: 100vh;
  box-sizing: border-box;
  background-color: var(--cp-bg);
  .van-pull-refresh {
    width: 100%;
    min-height: calc(100vh - 150px);
  }
}
</style>
